import FUtils from 'fo-utils';

const StringUtils = FUtils.StringUtils;

const isDev = FUtils.EnvironmentUtils.isDevelopment;

class ServiceApi {
    constructor(name, fetchApi) {
        this.name = name;
        this.host = fetchApi.host;
        this.port = fetchApi.port;
        this.api = fetchApi;
    }

    Get(url, {query, urlData}) {
        let param = {
            query,
            urlData
        };
        return this.__fetchResult(this.api.Get(url, param), 'GET', url, param);
    }

    Post(url, {query, urlData, body, headers}) {
        let param = {
            query,
            urlData,
            body,
            headers,
        };
        return this.__fetchResult(this.api.Post(url, param), 'POST', url, param);
    }

    Put(url, {query, urlData, body, headers}) {
        let param = {
            query,
            urlData,
            body,
            headers,
        };
        return this.__fetchResult(this.api.Put(url, param), 'PUT', url, param);
    }

    Delete(url, {query, urlData, headers}) {
        let param = {
            query,
            urlData,
            headers,
        };
        return this.__fetchResult(this.api.Delete(url, param), 'DELETE', url, param);
    }

    __fetchResult(api, method, url, param) {
        return api.then(response => this.__processResponses(response, method, url, param))
            .catch(error => ServiceApi._errorHandler(error).then(error => {
                throw error;
            }));
    }

    __processResponses(response, method, url, {query, urlData, body, header}) {
        return ServiceApi._responseHandler(response, {
            host: this.host,
            port: this.port,
            name: this.name,
            url,
            query,
            header,
            body,
            urlData,
            method
        });
    }

    static _dataHandler(response) {
        if (response.headers.has('Content-Type')) {
            let contentType = response.headers.get('Content-Type');
            if (contentType.indexOf('application/json') !== -1) {
                return response.json();
            }
        }
        return response.text();
    }

    static _responseHandler(response, {name, host, port, url, query, header, body, urlData, method}) {
        return ServiceApi._dataHandler(response).then(resBody => {
            if (isDev) {
                ServiceApi._debugConsole(name, host, port, url, {
                    query,
                    header,
                    body,
                    urlData,
                    method,
                    resBody: resBody,
                    resText: response.statusText,
                    resStatus: response.status
                });
            }
            return resBody
        });
    }

    static _errorHandler(error) {
        error.status = error.response.status;
        return error.response.text().then(body => {
            return new ServiceError({
                status: error.response.status,
                message: body
            });
        });
    }

    static _debugConsole(name, host, port, url, {query, header, body, urlData, method, resBody, resStatus, resText}) {
        method = StringUtils.fixLength(method, 6, " ", true);
        let str = `%c Service Api Log %c  ${name} \n${method} - ${host}:${port}${url}\nrequest: %O \nresponse: %O`;
        let css = 'background:#35495e ; padding: 1px; border-radius: 3px;  color: #fff';
        console.log(str, css, "",
            {
                urlData: urlData,
                query: query,
                header: header,
                body: body
            },
            {
                body: resBody,
                status: resStatus,
                statusText: resText,
            }
        );
    }
}

class ServiceError {
    constructor({status, message}) {
        this.message = message;
        this.status = status;
    }

}

export {ServiceError};
export default ServiceApi;